package com.onpositive.dataminer.rcp.utils;

import com.onpositive.knowledge.model.IThing;
import com.onpositive.knowledge.model.values.DescribedValue;
import com.onpositive.knowledge.model.values.IHasValue;
import com.onpositive.knowledge.model.values.PropertyValuePair;
import com.onpositive.semantic.model.api.meta.IHasMeta;
import com.onpositive.semantic.model.binding.AbstractBinding;
import com.onpositive.semantic.model.binding.Binding;
import com.onpositive.semantic.model.ui.generic.Column;
import com.onpositive.semantic.model.ui.richtext.IParentDependingRichLabelProvider;
import com.onpositive.semantic.model.ui.richtext.StyledString;
import com.onpositive.semantic.model.ui.richtext.StyledString.Style;
import com.onpositive.units.ParsedDate;
import com.onpositive.units.ParsedDimension;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedScalar;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.ParsedValueSequenceV2;

public class ValueLabelProvider implements IParentDependingRichLabelProvider{

	private static final long serialVersionUID = 981928302376602304L;

	@Override
	public String getText(IHasMeta meta, Object parent, Object object) {

		return object.toString();
	}

	@Override
	public String getDescription(Object object) {
		return object.toString();
	}

	@Override
	public StyledString getRichTextLabel(Object object) {
		
		String str = "";
		IHasValue value = extractValue(object, null);
		if(value != null){
			str = value.toString();
		}
		else if(object != null){
			str = object.toString();			
		}
		return new StyledString(str);
	}

	@Override
	public StyledString getRichTextLabel(IHasMeta env, Object object, Object value)
	{
		if((object instanceof PropertyValuePair)&&(value instanceof PropertyValuePair)){
			object = ((PropertyValuePair)object).getTarget();
			return new StyledString( ((IThing)object).getId() );			
		}
		
		if((object instanceof IThing) && (value instanceof IThing)){
			return new StyledString( ((IThing)value).getId() );
		}
		
		IHasValue val = extractValue(object,value);		
		boolean merge = mergeEnabled(env);
		if(!merge){
			return new StyledString(val!=null?val.toString():"");
		}
		
		return paintValue(val,null);
	}
	
	private static final Style STYLE_REF = new Style("blue", null);
	private static final Style STYLE_NUM = new Style(null, null);
	private static final Style STYLE_DATE = new Style("magenta", null);
	
	static{
		STYLE_NUM.setFontStyle(Style.ITALIC);
	}

	private StyledString paintValue(Object value, StyledString sString) {
		
		if(sString==null)
			sString = new StyledString();
		
		if(value==null){
			return sString;
		}
		else if(!(value instanceof IHasValue)){
			sString.append(value.toString());			
		}
		else if(value instanceof DescribedValue){
			DescribedValue dv = (DescribedValue) value;
			Object val = dv.value();
			paintValue(val, sString);			
		}
		else if(value instanceof ParsedValueSequenceV2){
			ParsedValueSequenceV2 pvs = (ParsedValueSequenceV2) value;
			ParsedValue[] arr = pvs.getValuesArray();
			int l = arr.length;
			for(int i = 0 ; i < l; i++){
				ParsedValue memberValue = arr[i];
				paintValue(memberValue, sString);
				if(i<l-1){
					sString.append(", ");
				}
			}
		}
		else if(value instanceof ParsedIdent){
			ParsedIdent pi = (ParsedIdent) value;
			String str = pi.getCaption();
			if(str==null)
				str = pi.getRef();
			
			sString.append(str, STYLE_REF);
		}
		else if(value instanceof ParsedDimension){
			ParsedDimension pd = (ParsedDimension) value;
			String str = pd.toString();
			int i = str.length();
			for( ; !Character.isDigit(str.charAt(i-1)) && i>0 ; i-- );			
			sString.append(str.substring(0, i), STYLE_NUM);
			sString.append(str.substring(i));
		}
		else if(value instanceof ParsedScalar){
			ParsedScalar ps = (ParsedScalar) value;
			String str = ps.toString();
			sString.append(str, STYLE_NUM);
		}
		else if(value instanceof ParsedDate){
			ParsedDate pd = (ParsedDate) value;
			String str = pd.toString();
			sString.append(str, STYLE_DATE);
		}
		else{
			sString.append(value.toString());
		}
		return sString;
	}

	private IHasValue extractValue(Object object, Object value) {
		
		IHasValue result = null;
		while(true){			
			if(!(object instanceof PropertyValuePair))
				break;

			PropertyValuePair pair = (PropertyValuePair) object;
			result = pair.value;
			break;			
		}
		if(result==null &&(value instanceof IHasValue))
			result = (IHasValue) value;
		
		if((object instanceof IHasValue)&&(value instanceof Column))
			return (IHasValue) object;
		
		return result;
	}

	private boolean mergeEnabled(IHasMeta env) {
		
		if(!(env instanceof AbstractBinding))
			return true;
		
		AbstractBinding rootBnd = (AbstractBinding) env;
		while(rootBnd.getParent()!=null)
			rootBnd = rootBnd.getParent();
		
		Binding cmBnd = rootBnd.getChild("cleanMode");
		if(cmBnd==null)
			return true;
		
		Object val = cmBnd.getValue();
		if(!(val instanceof Boolean))
			return true;
		
		Boolean bVal = (Boolean) val; 
		return bVal;
	}
	
}
